package cn.kongnannan.circularavatar;

import ohos.agp.render.*;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.RectFloat;
import ohos.media.image.PixelMap;
import ohos.media.image.common.AlphaType;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.ScaleMode;
import ohos.media.image.common.Size;

import java.util.List;

/**
 * JoinBitmaps
 */
public class JoinBitmaps {
    private static PixelMap bitmap;
    /**
     * join
     *
     * @param canvas    Canvas
     * @param dimension Dimenstion
     * @param bitmaps   Bitmaps
     */
    public static void join(Canvas canvas, int dimension, List<PixelMap> bitmaps) {
        if (bitmaps == null) {
            return;
        }
        int count = Math.min(bitmaps.size(), JoinLayout.max());
        float[] size = JoinLayout.size(count);
        join(canvas, dimension, bitmaps, count, size);
    }

    /**
     * join
     *
     * @param canvas    Canvas
     * @param dimension Integer
     * @param bitmaps   PixelMap List
     * @param count     integer
     * @param size      float
     */
    public static void join(Canvas canvas, int dimension, List<PixelMap> bitmaps, int count,
                            float[] size) {
        join(canvas, dimension, bitmaps, count, size, Constants.DECIMAL_FIFTEEN_NUM_CONST);
    }

    /**
     * join
     *
     * @param canvas    Canvas
     * @param dimension Integer
     * @param bitmaps   List
     * @param gapSize   float
     */
    public static void join(Canvas canvas, int dimension, List<PixelMap> bitmaps,
                            float gapSize) {
        if (bitmaps == null)
            return;
        int count = Math.min(bitmaps.size(), JoinLayout.max());
        float[] size = JoinLayout.size(count);
        join(canvas, dimension, bitmaps, count, size, gapSize);
    }

    /**
     * join
     *
     * @param canvas    Canvas
     * @param dimension Integer
     * @param bitmaps   ListBitmap
     * @param count     integer
     * @param size      float
     * @param gapSize   float
     */
    public static void join(Canvas canvas, int dimension, List<PixelMap> bitmaps, int count,
                            float[] size, float gapSize) {
        if (bitmaps == null) {
            return;
        }
        float[] rotation = JoinLayout.rotation(count);
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Matrix matrixJoin = new Matrix();
        matrixJoin.postScale(size[Constants.ZERO_NUM_CONST], size[Constants.ZERO_NUM_CONST]);
        canvas.save();

        for (int index = Constants.ZERO_NUM_CONST; index < bitmaps.size(); index++) {
            bitmap = bitmaps.get(index);
            Matrix matrix = new Matrix();
            matrix.postScale((float) dimension / bitmap.getImageInfo().size.width,
                    (float) dimension / bitmap.getImageInfo().size.height);
            canvas.save();
            matrix.postConcat(matrixJoin);

            float[] offset = JoinLayout.offset(count, index, dimension, size);
            canvas.translate(offset[Constants.ZERO_NUM_CONST], offset[Constants.ONE_NUM_CONSTANT]);
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
            initializationOptions.size = new Size();
            initializationOptions.size.height = bitmap.getImageInfo().size.height;
            initializationOptions.size.width = bitmap.getImageInfo().size.width;
            PixelMap secondBitmap = createPixelMap(bitmap, Constants.ZERO_NUM_CONST, Constants.ZERO_NUM_CONST,
                    bitmap.getImageInfo().size.width,
                    bitmap.getImageInfo().size.height, matrix, true);
            PixelMap bitmapOk = createMaskBitmap(secondBitmap, secondBitmap.getImageInfo().size.width,
                    secondBitmap.getImageInfo().size.height, (int) rotation[index], gapSize);
            canvas.drawPixelMapHolder(new PixelMapHolder(bitmapOk), Constants.ZERO_NUM_CONST, Constants.ZERO_NUM_CONST, paint);
            canvas.restore();
        }
        canvas.restore();
    }

    /**
     * createPixelMap
     *
     * @param source PixelMap source
     * @param xval   integer
     * @param yval   integer
     * @param width  integer
     * @param height integer
     * @param matrix Matrix
     * @param filter boolean
     * @return pixelmap
     */
    public static PixelMap createPixelMap(PixelMap source, int xval, int yval, int width, int height,
                                          Matrix matrix, boolean filter) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        RectFloat srcR = new RectFloat(xval, yval, xval + width, yval + height);
        RectFloat dstR = new RectFloat(Constants.ZERO_NUM_CONST, Constants.ZERO_NUM_CONST, width, height);
        RectFloat deviceR = new RectFloat();
        Paint paint = new Paint();
        paint.setFilterBitmap(filter);
        final boolean transformed = !matrix.rectStaysRect();
        if (transformed) {
            paint.setAntiAlias(true);
        }
        matrix.mapRect(deviceR, dstR);

        int neww = Math.round(deviceR.getWidth());
        int newh = Math.round(deviceR.getHeight());
        initializationOptions.size = new Size(neww, newh);
        initializationOptions.scaleMode = ScaleMode.CENTER_CROP;
        initializationOptions.alphaType = AlphaType.OPAQUE;
        PixelMap srcPixelMap = PixelMap.create(initializationOptions);
        Texture texture = new Texture(srcPixelMap);
        Canvas canvas = new Canvas(texture);
        canvas.translate(-deviceR.left, -deviceR.top);
        canvas.concat(matrix);
        canvas.drawPixelMapHolderRect(new PixelMapHolder(source), srcR, dstR, paint);
        return srcPixelMap;
    }

    /**
     * createMaskBitmap
     *
     * @param bitmap   PixelMap
     * @param viewBoxW integer
     * @param viewBoxH integer
     * @param rotation integer
     * @param gapSize  float
     * @return PixelMap
     */
    public static PixelMap createMaskBitmap(PixelMap bitmap, int viewBoxW, int viewBoxH,
                                            int rotation, float gapSize) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.size = new Size();
        initializationOptions.size.height = viewBoxH;
        initializationOptions.size.width = viewBoxW;
        PixelMap output = PixelMap.create(initializationOptions);
        Canvas canvas = new Canvas(new Texture(output));

        final Paint paint = new Paint();
        paint.setAntiAlias(true);// 抗锯齿
        paint.setFilterBitmap(true);
        int center = Math.round(viewBoxW / Constants.TWO_FLOAT_NUM_CONSTANT);
        canvas.drawCircle(center, center, center, paint);
        paint.setBlendMode(BlendMode.SRC_IN);

        canvas.drawPixelMapHolder(new PixelMapHolder(bitmap), Constants.ZERO_NUM_CONST, Constants.ZERO_NUM_CONST, paint);

        if (rotation != Constants.THREE_SIXTY_NUM_CONST) {
            Matrix matrix = new Matrix();
            matrix.setRotate(rotation, viewBoxW / Constants.TWO_NUM_CONSTANT, viewBoxH / Constants.TWO_NUM_CONSTANT);
            canvas.setMatrix(matrix);
            paint.setBlendMode(BlendMode.CLEAR);
            canvas.drawCircle(viewBoxW * (Constants.ONE_POINT_FIVE_NUM_CONST - gapSize), center, center, paint);
        }
        return output;
    }

    /**
     * createBitmap
     *
     * @param width   inetegr
     * @param height  integer
     * @param bitmaps List
     * @return PixelMap
     */
    public static PixelMap createBitmap(int width, int height, List<PixelMap> bitmaps) {
        int count = Math.min(bitmaps.size(), JoinLayout.max());
        float[] size = JoinLayout.size(count);
        return createBitmap(width, height, bitmaps, count, size, Constants.DECIMAL_FIFTEEN_NUM_CONST);
    }

    /**
     * createBitmap
     *
     * @param width   integer
     * @param height  integer
     * @param bitmaps List
     * @param count   integer
     * @param size    Float
     * @return PixelMap
     */
    public static PixelMap createBitmap(int width, int height, List<PixelMap> bitmaps,
                                        int count, float[] size) {
        return createBitmap(width, height, bitmaps, count, size, Constants.DECIMAL_FIFTEEN_NUM_CONST);
    }

    /**
     * createBitmap
     *
     * @param width   integer
     * @param height  inetegr
     * @param bitmaps ineteger
     * @param count   integer
     * @param size    float
     * @param gapSize float
     * @return PixelMap
     */
    public static PixelMap createBitmap(int width, int height, List<PixelMap> bitmaps,
                                        int count, float[] size, float gapSize) {
        PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
        initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
        initializationOptions.size = new Size();
        initializationOptions.size.height = height;
        initializationOptions.size.width = width;
        PixelMap output = PixelMap.create(initializationOptions);
        Canvas canvas = new Canvas(new Texture(output));
        int dimen = Math.min(width, height);
        join(canvas, dimen, bitmaps, count, size, gapSize);
        return output;
    }
}
